package com.yenlien.traceyun.usercenter.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.common.crypt.CryptUtil;
import com.yenlien.traceyun.common.utils.Tools;
import com.yenlien.traceyun.usercenter.dao.*;
import com.yenlien.traceyun.usercenter.entity.*;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: bigwangy@sina.com
 * @create: 2020-07-21
 * @description:
 **/

@Service
public class CompanyService {

    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private CompanyCustomAppVersionDao companyCustomAppVersionDao;
    @Autowired
    private ResourceDao resourceDao;
    @Autowired
    private UserResourceDao userResourceDao;
    @Autowired
    private FileService fileService;
    @Autowired
    private OtherMaterialService otherMaterialService;
    @Autowired
    private CompanyShowDao companyShowDao;


    public Page<Company> findByList(final Company company) {
        Pageable pageable = PageRequest.of(company.getPage(), company.getPageSize(), Sort.Direction.DESC, "createtime");
        return companyDao.findAll(new Specification<Company>() {
            @Override
            public Predicate toPredicate(Root<Company> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //构造查询条件
                List<Predicate> list = new ArrayList<>();
                if (!StringUtils.isEmpty(company.getType())) {
                    list.add(cb.equal(root.get("type"), company.getType()));
                }
                if (!StringUtils.isEmpty(company.getName())) {
                    list.add(cb.like(root.get("name"), "%" + company.getName() + "%"));
                }
                if (!StringUtils.isEmpty(company.getParentId())) {
                    list.add(cb.equal(root.get("parentId"), company.getParentId()));
                }
                if (!StringUtils.isEmpty(company.getExamined())) {
                    list.add(cb.equal(root.get("examined"), company.getExamined()));
                }
                list.add(cb.equal(root.get("state"), 0));
                Predicate[] predicate = new Predicate[list.size()];
                return cb.and(list.toArray(predicate));
            }
        }, pageable);
    }

    public List<Company> findFruitCompList(Company company) {
//        Pageable pageable = PageRequest.of(company.getPage(), company.getPageSize(), Sort.Direction.DESC, "createtime");
        return companyDao.findAll((Root<Company> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
                List<Predicate> list = new ArrayList<>();
                if (!StringUtils.isEmpty(company.getParentId())) {
                    list.add(cb.equal(root.get("parentId"), company.getId()));
                }
                Predicate[] predicate = new Predicate[list.size()];
                return cb.and(list.toArray(predicate));
        });
    }

    public List<Company> findAllFruitCompList() {
        return companyDao.findByType("1");
    }

    public Company findById(String id) {
        Company company = companyDao.findById(id);
        User p = userDao.findById(company.getUserId());
        company.setUs(p);
        company.setMaterialList(otherMaterialService.findByRelevanceId(id));
        return company;
    }

    public Company findParentById(String id) {
        return companyDao.findParentById(id);
    }

    public String findTypeById(String id) {
        Company company = companyDao.findById(id);
        if (company == null) {
            return "";
        }
        return company.getType();
    }

    /**
     * 检验参数
     *
     * @param company
     */
    private void check(Company company) {
        //添加
        if (StringUtils.isEmpty(company.getId())) {
//            Company p = companyDao.findByPhone(company.getPhone());
//            if(p!=null){
//                throw new BusinessException("500","企业电话已存在");
//            }
            Company p2 = companyDao.findByName(company.getName());
            if (p2 != null) {
                throw new BusinessException("500", "企业名称已存在");
            }
            if (company.getUs() != null) {
                if (StringUtils.isEmpty(company.getUs().getUsername())) {
                    User user = userDao.findByUsername(company.getUs().getUsername());
                    if (user != null) {
                        throw new BusinessException("500", "用户名已存在");
                    }
                }
            }
        } else {//修改
//            Company p = companyDao.findByPhone(company.getPhone());
//            if(p!=null && !p.getId().equals(company.getId())){
//                throw new BusinessException("500","企业电话已存在");
//            }
            Company p2 = companyDao.findByName(company.getName());
            if (p2 != null && !p2.getId().equals(company.getId())) {
                throw new BusinessException("500", "企业名称已存在");
            }
            if (company.getUs() != null) {
                if (StringUtils.isEmpty(company.getUs().getUsername())) {
                    User user = userDao.findByUsername(company.getUs().getUsername());
                    if (user != null && !user.getId().equals(company.getUs().getId())) {
                        throw new BusinessException("500", "用户名已存在");
                    }
                }
            }
        }
    }


    /**
     * 添加企业，并初始化企业用户
     *
     * @param company
     * @return
     */
    @Transactional
    public Company save(Company company, List<MultipartFile> files) throws Exception {
        if (!StringUtils.isEmpty(company.getUser())) {
            company.setUs(JSONObject.toJavaObject(JSONObject.parseObject(company.getUser()), User.class));
        }
        /**
         * 以下注释代码是因为：12222添加企业账户，查询不到企业信息，有待处理
         * */
//        if(org.apache.commons.lang3.StringUtils.isBlank(company.getId())){
//            // 添加政企的企业数量限制
//            if("1".equals(company.getType())){
//                String parentId = company.getParentId();
//                if(org.apache.commons.lang3.StringUtils.isNotBlank(parentId)){
//                    // 获取该政企最多能添加的企业个数,  不能配置相同的产品否则这里就查出了多个
//                    CompanyCustomAppVersion byParentId = companyCustomAppVersionDao.findByParentId(parentId);
//                    int companyNum = byParentId.getCompanyNum();
//                    // 查询该企业已经添加的企业数量
//                    int countByParentId = companyDao.getCountByParentId(parentId);
//                    if(countByParentId >= companyNum){
//                        throw new BusinessException("该政管的企业数已达最大, 不能再新建。最多限制数量: " + company + ", 已创建的企业数量: " + countByParentId);
//                    }
//                }
//            }
//        }
        check(company);
        if (files.size() > 0) {
            fileService.upload(null, company, files);
        }
        User user = company.getUs();
        if (user == null) {
            user = new User();
        }
        if (!StringUtils.isEmpty(company.getParentId())) {
            company.setParentName(companyDao.findById(company.getParentId()).getName());
        }
        user.setCreatetime(new Date());
        if (StringUtils.isEmpty(user.getUsername())) {
            user.setUsername(company.getLegalPhone());
        }
        if (StringUtils.isEmpty(user.getPhone())) {
            user.setPhone(company.getLegalPhone());
        }
        if (StringUtils.isEmpty(user.getPassword())) {
            user.setPassword(CryptUtil.md5("123456"));
        } else {
            user.setPassword(CryptUtil.md5(user.getPassword()));
        }
        if (company.getType().equals("1")) {
            user.setUserType(User.UserType.COMPANY);
        } else if (company.getType().equals("2")) {
            user.setUserType(User.UserType.GOV);
        } else {
            user.setUserType(User.UserType.COMPANY);
        }
        String type = company.getType();
        // 修改Bug  type=  1企业 2 政府 3代理商,0系统内置
        if ("1".equals(type)) {
            // 企业是以运营人手机号作为登陆账号
            user.setPhone(company.getOperatePhone());
        } else if ("2".equals(type) || "3".equals(type)) {
            // 政府和代理商 这 username 就是登录账号(也是手机号,所以政府这边就没有名称)
            user.setPhone(company.getUs().getUsername());
        }
        userDao.save(user);
        company.setUserId(user.getId());
        company.setCreatetime(Tools.getCurrentTime());
        companyDao.save(company);
        user.setCompanyId(company.getId());
        userDao.save(user);
        if (!StringUtils.isEmpty(company.getMaterials())) {
            List<OtherMaterial> materialList = JSONArray.parseArray(company.getMaterials(), OtherMaterial.class);
            otherMaterialService.save(materialList, company.getId(), files);
        }
        if (!StringUtils.isEmpty(company.getVersionsString())) {
            List<CompanyCustomAppVersion> versions = JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class);
            if (versions != null && versions.size() > 0) {
                for (CompanyCustomAppVersion companyCustomAppVersion : versions) {
                    companyCustomAppVersion.setCompanyId(company.getId());
                }
            }
            // 不能选择同样产品, 按产品ID去重
            List<String> list = versions.stream().map(CompanyCustomAppVersion::getCustomAppVersionId).distinct().collect(Collectors.toList());
            if (versions.size() != list.size()) {
                throw new BusinessException("不能选择同样产品");
            }
            companyCustomAppVersionDao.saveAll(versions);
//            company.setVersions(JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class));
//            bindApp(company.getId(), company.getVersions()); //企业绑定应用
        }
        // 添加企业秀信息，调用 /plant/company/save 是会添加企业秀,但新增企业掉的是 /control
        if ("1".equals(type)) {
            CompanyShow show = new CompanyShow();
            show.setCompanyId(company.getId());
            show.setCode(company.getId());
            companyShowDao.save(show);
        }
        return company;
    }


    @Transactional
    public Company save2(Company company) throws Exception {
        if (!StringUtils.isEmpty(company.getUser())) {
            company.setUs(JSONObject.toJavaObject(JSONObject.parseObject(company.getUser()), User.class));
        }
        check(company);
        User user = company.getUs();
        if (user == null) {
            user = new User();
        }
        if (!StringUtils.isEmpty(company.getParentId())) {
            company.setParentName(companyDao.findById(company.getParentId()).getName());
        }
        user.setCreatetime(new Date());
        if (StringUtils.isEmpty(user.getUsername())) {
            user.setUsername(company.getLegalPhone());
        }
        if (StringUtils.isEmpty(user.getPhone())) {
            user.setPhone(company.getLegalPhone());
        }
        if (StringUtils.isEmpty(user.getPassword())) {
            user.setPassword(CryptUtil.md5("123456"));
        } else {
            user.setPassword(CryptUtil.md5(user.getPassword()));
        }
        if (company.getType().equals("1")) {
            user.setUserType(User.UserType.COMPANY);
        } else if (company.getType().equals("2")) {
            user.setUserType(User.UserType.GOV);
        } else {
            user.setUserType(User.UserType.COMPANY);
        }
        String type = company.getType();
        // 修改Bug  type=  1企业 2 政府 3代理商,0系统内置
        if ("1".equals(type)) {
            // 企业是以运营人手机号作为登陆账号
            user.setPhone(company.getOperatePhone());
        } else if ("2".equals(type) || "3".equals(type)) {
            // 政府和代理商 这 username 就是登录账号(也是手机号,所以政府这边就没有名称)
            user.setPhone(company.getUs().getUsername());
        }
        userDao.save(user);
        company.setUserId(user.getId());
        company.setCreatetime(Tools.getCurrentTime());
        companyDao.save(company);
        user.setCompanyId(company.getId());
        userDao.save(user);
        if (!StringUtils.isEmpty(company.getMaterials())) {
            List<OtherMaterial> materialList = JSONArray.parseArray(company.getMaterials(), OtherMaterial.class);
        }
        if (!StringUtils.isEmpty(company.getVersionsString())) {
            List<CompanyCustomAppVersion> versions = JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class);
            if (versions != null && versions.size() > 0) {
                for (CompanyCustomAppVersion companyCustomAppVersion : versions) {
                    companyCustomAppVersion.setCompanyId(company.getId());
                }
            }
            // 不能选择同样产品, 按产品ID去重
            List<String> list = versions.stream().map(CompanyCustomAppVersion::getCustomAppVersionId).distinct().collect(Collectors.toList());
            if (versions.size() != list.size()) {
                throw new BusinessException("不能选择同样产品");
            }
            companyCustomAppVersionDao.saveAll(versions);
//            company.setVersions(JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class));
//            bindApp(company.getId(), company.getVersions()); //企业绑定应用
        }
        // 添加企业秀信息，调用 /plant/company/save 是会添加企业秀,但新增企业掉的是 /control
        if ("1".equals(type)) {
            CompanyShow show = new CompanyShow();
            show.setCompanyId(company.getId());
            show.setCode(company.getId());
            companyShowDao.save(show);
        }
        return company;
    }








    @Transactional
    public Company update(Company company, List<MultipartFile> files) throws Exception {
        if (!StringUtils.isEmpty(company.getUser())) {
            company.setUs(JSONObject.toJavaObject(JSONObject.parseObject(company.getUser()), User.class));
        }
        check(company);
        fileService.upload(companyDao.findById(company.getId()), company, files);
        Company p = companyDao.save(company);
        userDao.save(company.getUs());
        if (!StringUtils.isEmpty(company.getMaterials())) {
            List<OtherMaterial> materialList = JSONArray.parseArray(company.getMaterials(), OtherMaterial.class);
            otherMaterialService.save(materialList, company.getId(), files);
        }
        if (!StringUtils.isEmpty(company.getVersionsString())) {
            company.setVersions(JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class));
            Set<UserResource> userResources = new HashSet<>();
            Set<CompanyCustomAppVersion> customAppVersions = new HashSet<>();
            for (CompanyCustomAppVersion customAppVersion : company.getVersions()) {
                customAppVersions.add(companyCustomAppVersionDao.findByAppIdAndCompanyId(customAppVersion.getAppId(), company.getId()));
                userResources.addAll(userResourceDao.findByUserIdAndAppId(company.getUserId(), customAppVersion.getAppId()));
            }
            companyCustomAppVersionDao.deleteAll(customAppVersions);
            userResourceDao.deleteAll(userResources);
            bindApp(company.getId(), company.getVersions()); //企业绑定应用
        }
        return p;
    }


    @Transactional
    public Company update2(Company company) throws Exception {
        if (!StringUtils.isEmpty(company.getUser())) {
            company.setUs(JSONObject.toJavaObject(JSONObject.parseObject(company.getUser()), User.class));
        }
        check(company);
        Company p = companyDao.save(company);
        userDao.save(company.getUs());
        if (!StringUtils.isEmpty(company.getMaterials())) {
            List<OtherMaterial> materialList = JSONArray.parseArray(company.getMaterials(), OtherMaterial.class);
            otherMaterialService.save2(materialList, company.getId());
        }
        if (!StringUtils.isEmpty(company.getVersionsString())) {
            company.setVersions(JSONArray.parseArray(company.getVersionsString(), CompanyCustomAppVersion.class));
            Set<UserResource> userResources = new HashSet<>();
            Set<CompanyCustomAppVersion> customAppVersions = new HashSet<>();
            for (CompanyCustomAppVersion customAppVersion : company.getVersions()) {
                customAppVersions.add(companyCustomAppVersionDao.findByAppIdAndCompanyId(customAppVersion.getAppId(), company.getId()));
                userResources.addAll(userResourceDao.findByUserIdAndAppId(company.getUserId(), customAppVersion.getAppId()));
            }
            companyCustomAppVersionDao.deleteAll(customAppVersions);
            userResourceDao.deleteAll(userResources);
            bindApp(company.getId(), company.getVersions()); //企业绑定应用
        }
        return p;
    }


    public Company updateInfo(Company company)  {
        return companyDao.save(company);
    }

    /**
     * 企业绑定自定义应用
     *
     * @param apps
     */
    public void bindCompanyAppVersion(List<CompanyCustomAppVersion> apps) {
        companyCustomAppVersionDao.saveAll(apps);

    }

    /**
     * 企业绑定应用
     *
     * @param companyId
     * @param apps
     * @return
     */
    @Transactional
    public void bindApp(String companyId, List<CompanyCustomAppVersion> apps) {
        //企业绑定应用
        Company company = companyDao.findById(companyId);
        if (apps != null && apps.size() > 0) {
            for (CompanyCustomAppVersion app : apps) {
                app.setCompanyId(companyId);
            }
            companyCustomAppVersionDao.saveAll(apps);
        }
        //生成企业用户权限
        List<Resource> resources = resourceDao.findByCompanyId(companyId);
        if (resources != null && resources.size() > 0) {
            List<UserResource> userResources = new ArrayList<>();
            for (Resource resource : resources) {
                UserResource userResource = new UserResource();
                userResource.setAppId(resource.getAppId());
                userResource.setResourceId(resource.getId());
                userResource.setUserId(company.getUserId());
                userResources.add(userResource);
            }
            userResourceDao.saveAll(userResources);
        }
    }

    @Transactional
    public void delete(String id) {
        Company company = companyDao.findById(id);
        company.setState(1);
        companyDao.save(company);
        User user = userDao.findById(company.getUserId());
        user.setLocked(true);
        userDao.save(user);
    }

    /**
     * 查询有多少条数据
     *
     * @return
     */
    public int number() {
        List<Company> all = companyDao.findAll();
        int size = all.size();
        return size;
    }

    /**
     * 查询企业新增
     *
     * @return
     */
    public Object newCompanys() {
        Date date = new Date();
        SimpleDateFormat sformat = new SimpleDateFormat("yyyy-MM-dd");//日期格式
        String date1 = sformat.format(date);
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        Integer month = ca.get(Calendar.MONTH) + 1;
        Integer year = ca.get(Calendar.YEAR);
        String dateStr = year.toString() + "-" + month.toString() + "-01";
        List<Integer> arr = new ArrayList<>();
        try {
            Date startDate = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);    //当前月
            List<Company> byProfessionAndCreatetimeBetween1 = companyDao.findByCreatetimeBetween(dateStr, date1);
            if (!StringUtils.isEmpty(byProfessionAndCreatetimeBetween1)) {
                arr.add(0, byProfessionAndCreatetimeBetween1.size());
            } else {
                arr.add(0, 0);
            }
            Calendar ca1 = Calendar.getInstance();
            ca1.setTime(startDate);
            for (int i = 1; i < 12; i++) {
                Date ca1Time = ca1.getTime();
                String date2 = sformat.format(ca1Time);
                ca1.add(Calendar.MONTH, -1);
                String date3 = sformat.format(ca1Time);
                List<Company> byProfessionAndCreatetimeBetween = companyDao.findByCreatetimeBetween(date2, date3);
                if (byProfessionAndCreatetimeBetween.size() != 0) {
                    arr.add(i, byProfessionAndCreatetimeBetween1.size());
                } else {
                    arr.add(i, 0);
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return arr;

    }

    public Object cumCompanys() {
        Date date = new Date();
        SimpleDateFormat sformat = new SimpleDateFormat("yyyy-MM-dd");//日期格式
        String date1 = sformat.format(date);
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        String dateStr = "2021-01-01";//2021年开始
        List<Integer> arr = new ArrayList<>();
        try {
            Date startDate = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
            List<Company> byProfessionAndCreatetimeBetween1 = companyDao.findByCreatetimeBetween(dateStr, date1);
            if (!StringUtils.isEmpty(byProfessionAndCreatetimeBetween1)) {
                arr.add(0, byProfessionAndCreatetimeBetween1.size());
            } else {
                arr.add(0, 0);
            }
            Calendar ca1 = Calendar.getInstance();
            ca1.setTime(startDate);
            for (int i = 1; i < 12; i++) {
                Date ca1Time = ca1.getTime();
                ca1.add(Calendar.MONTH, -1);
                String date2 = sformat.format(ca1Time);
                List<Company> byProfessionAndCreatetimeBetween = companyDao.findByCreatetimeBetween(dateStr, date2);
                if (byProfessionAndCreatetimeBetween.size() != 0) {
                    arr.add(i, byProfessionAndCreatetimeBetween1.size());
                } else {
                    arr.add(i, 0);
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return arr;
    }

    /**
     * 查询数据中心企业数量
     *
     * @return
     */
    public Object firm(String companyId) {
        int size = companyDao.findByParentId(companyId).size();
        return size;
    }

    /**
     * 查询已审核公司
     *
     * @param audit
     * @return
     */
    public Object audit(String audit) {
        return companyDao.findByExamined(audit);

    }
}
